using System;
using System.IO.Ports;

namespace 燃油加注机指令翻译
{
    public partial class Form1 : Form
    {
        SerialPort serialPort;
        public Form1()
        {
            InitializeComponent();

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.SelectedIndex = 0;
            comboBox2.SelectedIndex = 0;
        }

        /// <summary>
        /// 串口链接
        /// </summary>
        private void ComConnection()
        {
            try
            {
                serialPort = new SerialPort();
                // 设置串口参数
                serialPort.PortName = comboBox1.SelectedItem.ToString(); // 串口端口号，根据实际情况设置
                serialPort.BaudRate = 9600; // 波特率，根据实际情况设置
                serialPort.Parity = Parity.Even; // 校验位 偶校验
                serialPort.DataBits = 8; // 数据位
                serialPort.StopBits = StopBits.One; // 停止位


                //这里同步、异步接收数据只能选择一种

                //异步接收数据
                serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);

                //同步接收数据
                //while (true)
                //{
                //    string data = serialPort.ReadLine();
                //    if (!string.IsNullOrWhiteSpace(data)) 
                //    {
                //        this.WriteMessage(data);
                //    }
                //    // 如果需要处理二进制数据，可以使用以下方法
                //    // byte[] buffer = new byte[serialPort.BytesToRead];
                //    // serialPort.Read(buffer, 0, buffer.Length);
                //    // Console.WriteLine("Binary data received: " + BitConverter.ToString(buffer));
                //}

                serialPort.Open();


                if (serialPort.IsOpen)
                {
                    button7.Text = "已连接";
                    button7.Enabled = false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("加油机连接失败：" + ex.Message);
                //throw new Exception("加油机连接失败：" + ex.Message);

            }
            //finally
            //{
            //    if (serialPort != null && !serialPort.IsOpen)
            //    {
            //        serialPort.Close();
            //    }
            //}


        }

        /// <summary>
        /// 异步接收串口数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            if (sp != null)
            {
                //string data = serialPort.ReadExisting();
                int bytesToRead = sp.BytesToRead;

                byte[] buffer = new byte[bytesToRead];
                sp.Read(buffer, 0, bytesToRead);
                string hexData = BitConverter.ToString(buffer).Replace("-", " ");
                if (!string.IsNullOrWhiteSpace(hexData))
                {
                    this.WriteMessage(hexData);
                }

            }
        }

        /// <summary>
        /// 写消息
        /// </summary>
        /// <param name="data"></param>
        public void WriteMessage(string data)
        {
            if (returnMessage.InvokeRequired)
            {
                returnMessage.Invoke(new Action<string>(WriteMessage), [data]);
            }
            else
            {
                returnMessage.Text = data;
            }
            this.analysisData(data);
        }

        void analysisData(string data)
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            string result, type;
            if (data.Replace(" ", "").Length>6)
            {
                data = data.Replace(" ", "").Substring(6);
            }
            else
            {
                return;
            }
            switch (comboBox2.SelectedItem)
            {
                case "送定量":
                    {
                        data = data.Substring(4);
                        result = data.Substring(0, 2);
                        switch (result)
                        {
                            case "BB": responseAnalysis.Text = "成功"; break;
                            case "DD": responseAnalysis.Text = "单价错误"; break;
                        }
                    }; break;
                //case "送单价":
                //    {
                //        PriceLabel.Text = ConvertDecimalToHex(Price.Text, 1, 2);
                //        ReciprocalLabel.Text = ConvertDecimalToHex(Reciprocal.Text, 1, 3);

                //        SendPrice price = new SendPrice();

                //        price.Price = PriceLabel.Text;
                //        price.Reciprocal = ReciprocalLabel.Text;

                //        Instruction.Text = price.instructionsHex();
                //    }; break;
                case "取消定量":
                    {
                        data = data.Substring(4);
                        result = data.Substring(0, 2);

                        switch (result)
                        {
                            case "BB": responseAnalysis.Text = "成功"; break;
                            case "CC": responseAnalysis.Text = "不允许：正在加油/已加/不存在"; break;
                        }
                    }; break;
                case "读实时数":
                    {
                        type = data.Substring(0, 2);
                        result = data.Substring(4, 6);
                        switch (type)
                        {
                            case "34": responseAnalysis.Text = "燃油加注量：" + ConvertHexToDecimal(result, 2, 1).Trim('0') + "升"; break;
                            case "35": responseAnalysis.Text = "燃油加注金额：" + ConvertHexToDecimal(result, 2, 1).Trim('0') + "元"; break;
                        }
                    }; break;
            }
        }

        void sendData(string data)
        {
            byte[] bytes = Tool.HexStringToByteArray(data.Replace(" ", ""));
            serialPort.Write(bytes, 0, bytes.Length);
        }


        //十六进制转BCD,各种参数值只使用0-9，以十六进制传输，但译码时按照直接对应的数字转成十进制

        static string ConvertHexToDecimal(string hexValue, int intLength, int decimalLength)
        {
            intLength *= 2;
            decimalLength *= 2;
            string format = "";
            for (int i = 0; i < intLength; i++)
            {
                format += "0";
            }
            format += ".";
            for (int i = 0; i < decimalLength; i++)
            {
                format += "0";
            }
            string intPart = hexValue.Substring(0, intLength);
            string decimalPart = hexValue.Substring(intLength, decimalLength);

            return decimal.Parse(intPart + "." + decimalPart).ToString(format);
        }

        //BCD转十六进制
        static string ConvertDecimalToHex(string decimalValue, int intLength, int decimalLength)
        {
            intLength *= 2;
            decimalLength *= 2;
            string format = "";
            for (int i = 0; i < intLength; i++)
            {
                format += "0";
            }
            format += ".";
            for (int i = 0; i < decimalLength; i++)
            {
                format += "0";
            }
            decimalValue = decimal.Parse(decimalValue).ToString(format);
            //if (decimalValue.Split(".")[1].TrimEnd('0') != "")
            //{
            //    decimalValue = decimalValue.TrimEnd('0');
            //}
            string intPart = decimalValue.Split(".")[0];
            string decimalPart = decimalValue.Split(".")[1];
            return intPart.PadLeft(intLength, '0') + decimalPart.PadRight(decimalLength, '0');
        }


        private void button1_Click(object sender, EventArgs e)
        {
            string instructionsHex = Instruction.Text.Replace(" ", "").Replace("\n", "").Replace("\r", "");

            Addition addition = new Addition();

            HexMapper.MapHexToClass(instructionsHex, addition);

            LitterLabel.Text = addition.Litter;
            AmountLabel.Text = addition.Amount;
            KilogramLabel.Text = addition.Kilogram;
            PriceLabel.Text = addition.Price;
            ReciprocalLabel.Text = addition.Reciprocal;
            FlagLabel.Text = addition.Flag;
            ChainLabel.Text = addition.Chain;

            Litter.Text = ConvertHexToDecimal(addition.Litter, 2, 1);
            Amount.Text = ConvertHexToDecimal(addition.Amount, 2, 1);
            Kilogram.Text = ConvertHexToDecimal(addition.Kilogram, 2, 1);
            Price.Text = ConvertHexToDecimal(addition.Price, 1, 2);
            Reciprocal.Text = ConvertHexToDecimal(addition.Reciprocal, 1, 3);
            Flag.Text = Convert.ToInt32(addition.Flag, 16).ToString();
            Chain.Text = Convert.ToInt32(addition.Chain, 16).ToString();
        }

        private void button6_Click(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                byte[] bytes = Tool.HexStringToByteArray(Instruction.Text.Replace(" ", ""));
                serialPort.Write(bytes, 0, bytes.Length);
            }
            else
            {
                MessageBox.Show("请先打开连接");
            }

        }

        private void button7_Click(object sender, EventArgs e)
        {
            this.ComConnection();
        }

        private void button8_Click(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                button7.Text = "连接";
                button7.Enabled = true;
                serialPort.Close();
            }
        }

        private void button9_Click(object sender, EventArgs e)
        {
            switch (comboBox2.SelectedItem)
            {
                case "送定量":
                    {
                        LitterLabel.Text = ConvertDecimalToHex(Litter.Text, 2, 1);
                        AmountLabel.Text = ConvertDecimalToHex(Amount.Text, 2, 1);
                        KilogramLabel.Text = ConvertDecimalToHex(Kilogram.Text, 2, 1);
                        PriceLabel.Text = ConvertDecimalToHex(Price.Text, 1, 2);
                        ReciprocalLabel.Text = ConvertDecimalToHex(Reciprocal.Text, 1, 3);
                        FlagLabel.Text = Flag.Text.PadLeft(2, '0');
                        ChainLabel.Text = Chain.Text.PadLeft(4, '0');

                        Addition addition = new Addition();

                        addition.Litter = LitterLabel.Text;
                        addition.Amount = AmountLabel.Text;
                        addition.Kilogram = KilogramLabel.Text;
                        addition.Price = PriceLabel.Text;
                        addition.Reciprocal = ReciprocalLabel.Text;
                        addition.Flag = FlagLabel.Text;
                        addition.Chain = ChainLabel.Text;

                        Instruction.Text = addition.instructionsHex();
                    }; break;
                case "送单价":
                    {
                        PriceLabel.Text = ConvertDecimalToHex(Price.Text, 1, 2);
                        ReciprocalLabel.Text = ConvertDecimalToHex(Reciprocal.Text, 1, 3);

                        SendPrice price = new SendPrice();

                        price.Price = PriceLabel.Text;
                        price.Reciprocal = ReciprocalLabel.Text;

                        Instruction.Text = price.instructionsHex();
                    }; break;
                case "取消定量":
                    {
                        ChainLabel.Text = Chain.Text.PadLeft(4, '0');

                        Cancel cancel = new Cancel();

                        cancel.Chain = ChainLabel.Text;

                        Instruction.Text = cancel.instructionsHex();
                    }; break;
                case "读实时数":
                    {

                        ReadSingle readSingle = new ReadSingle();

                        Instruction.Text = readSingle.instructionsHex();
                    }; break;

            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            button9.PerformClick();
            button6.PerformClick();
        }

        private void Price_TextChanged(object sender, EventArgs e)
        {
            if (Price.Text != "" && double.Parse(Price.Text) != 0)
            {
                Amount.Text = (double.Parse(Price.Text) * double.Parse(Litter.Text)).ToString("0000.00");
                Reciprocal.Text = (1 / double.Parse(Price.Text)).ToString("00.000000");
            }

        }

        private void Litter_TextChanged(object sender, EventArgs e)
        {
            Amount.Text = (double.Parse(Price.Text) * double.Parse(Litter.Text)).ToString("0000.00");
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (serialPort.IsOpen)
            {
                Cancel cancelRefresh = new Cancel();
                cancelRefresh.Chain = 0.ToString().PadLeft(4, '0');
                sendData(cancelRefresh.instructionsHex());
                Thread.Sleep(500);
                Addition additionRefresh = new Addition();
                additionRefresh.Litter = ConvertDecimalToHex("0", 2, 1);
                additionRefresh.Amount = ConvertDecimalToHex("0", 2, 1);
                additionRefresh.Kilogram = ConvertDecimalToHex("0000.00", 2, 1);
                additionRefresh.Price = ConvertDecimalToHex(Price.Text, 1, 2);
                additionRefresh.Reciprocal = ConvertDecimalToHex("00.000000", 1, 3);
                additionRefresh.Flag = Flag.Text.PadLeft(2, '0');
                additionRefresh.Chain = 9999.ToString().PadLeft(4, '0');
                sendData(additionRefresh.instructionsHex());
                Thread.Sleep(500);
                Cancel cancel = new Cancel();
                cancel.Chain = 9999.ToString().PadLeft(4, '0');
                sendData(cancel.instructionsHex());
                Thread.Sleep(500);
                Addition addition = new Addition();
                addition.Litter = ConvertDecimalToHex(Litter.Text, 2, 1);
                addition.Amount = ConvertDecimalToHex(Amount.Text, 2, 1);
                addition.Kilogram = ConvertDecimalToHex("0000.00", 2, 1);
                addition.Price = ConvertDecimalToHex(Price.Text, 1, 2);
                addition.Reciprocal = ConvertDecimalToHex("00.000000", 1, 3);
                addition.Flag = Flag.Text.PadLeft(2, '0');
                addition.Chain = 0.ToString().PadLeft(4, '0');


                sendData(addition.instructionsHex());
            }
            else
            {
                MessageBox.Show("请先打开连接");
            }
        }
    }

}
